
#include "gameLayer.h"
#include "pumples.h"
using namespace std;

enum kinds {
	bgSprite,
	bgSprite2,
	ground,
	ground2,
	bird,
	pumple,
};

bool GameLayer::init()
{
	if (!Layer::init())
	{
		return false;
	}
	dir = Director::getInstance();
	vsize = dir->getVisibleSize();

	this->initTop();
	this->initBg();
	return true;
}

void GameLayer::onEnter()
{
	Layer::onEnter();
	scheduleUpdate();
}

void GameLayer::initBg()
{
	scoreLabel = Label::createWithTTF("0", "fonts/Marker Felt.ttf", 25);
	scoreLabel->setPositionNormalized(Vec2(0.5, 0.9));
	this->addChild(scoreLabel, 5);

//#pragma region 远景
	auto bgt2d = dir->getTextureCache()->addImage("res/bg.jpg");
	auto bgSprite = Sprite::createWithTexture(bgt2d);
	auto bgSprite2 = Sprite::createWithTexture(bgt2d);

	//两张图片相互循环拼接
	auto bgV2 = bgSprite->getPositionX() + bgSprite2->getContentSize().width;
	bgSprite->setPosition(vsize / 2);
	bgSprite2->setPosition(bgV2, vsize.height / 2);

	this->addChild(bgSprite, -1, kinds::bgSprite);
	this->addChild(bgSprite2, -1, kinds::bgSprite2);
//#pragma endregion

//#pragma region 近景
	auto t2d = dir->getTextureCache()->addImage("res/ground.png");
	//远景
	auto ground = Sprite::createWithTexture(t2d);
	auto ground2 = Sprite::createWithTexture(t2d);

	//两张图片相互循环拼接
	auto groundV2 = ground->getPosition() + Vec2(ground2->getContentSize().width, 0);
	ground2->setPosition(groundV2);

	this->addChild(ground, 0, kinds::ground);
	this->addChild(ground2, 0, kinds::ground2);
//#pragma endregion

//#pragma region create_Bird
	bird = Sprite::create("res/bird.png");
	bird->setPosition(vsize.width / 5, vsize.height / 2);

	auto bird_aminate = dir->getTextureCache()->addImage("res/bird_1_3.png");
	Vector<SpriteFrame*> spriteFrame;
	for (size_t i = 0; i < 3; i++)
	{
		auto size = bird_aminate->getContentSize();
		auto rect = Rect(size.width / 3 * i, 0, size.width / 3, size.height);
		spriteFrame.pushBack(SpriteFrame::createWithTexture(bird_aminate, rect));
	}
	auto animation = Animation::createWithSpriteFrames(spriteFrame, 0.2f);
	auto animate = Animate::create(animation);
	this->addChild(bird, 10, kinds::bird);

	auto repeat = RepeatForever::create(animate);
	bird->runAction(repeat);

	auto dispat = dir->getEventDispatcher();
	auto keyboard = EventListenerKeyboard::create();
	keyboard->onKeyPressed = [this](EventKeyboard::KeyCode code, Event* ev) {
		using key = EventKeyboard::KeyCode;
		if (key::KEY_SPACE == code)
		{
			if (!isRun)
				item1->activate();
			if (ev->getCurrentTarget()->getPositionY() < vsize.height)
			{
				velocity = 6;
			}
		}
	};
	dispat->addEventListenerWithSceneGraphPriority(keyboard, bird);

	//auto boxRect = PhysicsBody::createBox();
	//bird->setPhysicsBody();

//#pragma endregion

//#pragma region pumple

	auto down = dir->getTextureCache()->addImage("res/down_bar.png");
	auto up = dir->getTextureCache()->addImage("res/up_bar.png");
	auto downBar = Sprite::createWithTexture(down);
	auto upBar = Sprite::createWithTexture(up);

	/*auto spSize = downBar->getContentSize();
	float maxY =  spSize.height/2;
	float minY = -spSize.height / 4;

	float randY = random(minY, maxY);

	downBar->setPositionY(randY);
	upBar->setPositionY(randY + spSize.height+vsize.width/3);

	upBar->setPositionX(vsize.width/2);
	downBar->setPositionX(vsize.width/2);*/


	for (int i = 1; i < 5; i++)
	{
		auto pumple = Pumples::create(vsize.width * 0.6 * i + vsize.width);
		pumple->setTag(0);
		pumplesDeque.push_back(pumple);
		this->addChild(pumple, 2);
	}

//#pragma endregion
}

void GameLayer::initTop()
{
	item1 = MenuItemImage::create("start.png", "start.png", [this](Ref* r) {
		auto item1 = dynamic_cast<MenuItemImage*>(r);
		isRun = true;
		item1->stopAllActions();
		item1->removeFromParentAndCleanup(true);
		});
	item1->setScale(1.5);
	item1->setPositionNormalized(Vec2(0, 0.2));
	auto fadein = FadeIn::create(1.0f);
	auto fadeout = FadeOut::create(1.0f);
	auto seque = Sequence::create(fadeout, fadein, nullptr);
	auto rf = RepeatForever::create(seque);
	item1->runAction(rf);

	auto menu = Menu::create(item1, nullptr);
	this->addChild(menu);
}

void GameLayer::updateSorllBg(float dt)
{
	//远景滚动
	auto bgSprite = this->getChildByTag(kinds::bgSprite);
	auto bgSprite2 = this->getChildByTag(kinds::bgSprite2);

	auto width = bgSprite->getContentSize().width;
	bgSprite->setPositionX(bgSprite->getPositionX() - backgroundSpeed);
	bgSprite2->setPositionX(bgSprite->getPositionX() + width - backgroundSpeed);

	if (bgSprite2->getPositionX() < width / 2)
	{
		bgSprite->setPositionX(width / 2);
	}

	//前景滚动
	auto ground = this->getChildByTag(kinds::ground);
	auto ground2 = this->getChildByTag(kinds::ground2);

	auto width2 = ground->getContentSize().width;
	ground->setPositionX(ground->getPositionX() - foregroundSpeed);
	ground2->setPositionX(ground->getPositionX() + width2 - foregroundSpeed);

	if (ground2->getPositionX() < width2 / 2)
	{
		ground->setPositionX(width2 / 2);
	}

}

void GameLayer::updateBird(float dt)
{
	//小鸟移动
	auto bird = this->getChildByTag(kinds::bird);
	auto Y = bird->getPositionY();
	velocity -= gravity;
	bird->setPositionY(Y + velocity);

	//计算死亡
	auto ground = this->getChildByTag(kinds::ground);
	if (ground->getBoundingBox().containsPoint(bird->getPosition()))
	{
		newGame();
		return;
	}

	//撞水管死亡
	for (auto e : pumplesDeque) {
		auto b = e->convertToNodeSpace(bird->getPosition());
		auto rect1 = e->getChildren().at(0)->getBoundingBox();
		auto rect2 = e->getChildren().at(1)->getBoundingBox();
		if (rect1.containsPoint(b) ||
			rect2.containsPoint(b))
		{
			isRun = false;
			newGame();
			return;
		}
		//分数++
		if (e->getTag() != 1 && rect1.getMaxX() < b.x)
		{
			e->setTag(1);
			score++;
			scoreLabel->setString(to_string(score));
		}
	}


}

void GameLayer::updatePumple(float dt)
{
	for (auto e : pumplesDeque) {
		auto x = e->getPositionX() - foregroundSpeed;
		e->setPositionX(x);

		if (x < -vsize.width / 2)
		{
			this->removeChild(pumplesDeque.front());
			pumplesDeque.pop_front();
			auto pumple = Pumples::create(vsize.width * 0.6 + pumplesDeque.back()->getPositionX());
			pumplesDeque.push_back(pumple);
			this->addChild(pumple, 2);
			break;
		}
	}
}

void GameLayer::update(float dt)
{
	updateSorllBg(dt);
	if (isRun) {
		updateBird(dt);
		updatePumple(dt);
	}
}

void GameLayer::newGame()
{
	auto scene = Scene::create();
	auto layer = GameLayer::create();
	scene->addChild(layer);
	Director::getInstance()->replaceScene(scene);
}

GameLayer* GameLayer::create()
{
	GameLayer* ptr = new(nothrow) GameLayer();
	if (ptr && ptr->init()) {
		return ptr;
	}
	return nullptr;
}